<template>
  <div class="human-container">
    <div class="video-wrapper">
      <video id="video" class="demo-video" autoplay playsinline></video>
      <audio id="audio" autoplay></audio>
    </div>
    <div class="digital-human-features">
      <button id="start" @click="start">连线数字人</button>
      <button id="stop" @click="stop" style="display: none">断开连线</button>
      <input type="hidden" id="sessionid" value="0">
      <div class="question-section">
        <div class="input-container">
          <textarea v-model="question" placeholder="在此输入问题开始对话"></textarea>
          <button @click="sendQuestion">提问</button>
        </div>
      </div>
      <div class="record-section">
        <div class="audio-container">
          <audio id="audioPlayer" controls></audio>
          <button id="chat_btn" @click="handleRecord">{{ isRecording ? '录制中' : '语音' }}</button>
          <button id="upload_sound_btn" @click="uploadSound">发送</button>
        </div>
      </div>
      <div class="log-section">
        <textarea id="chatlog" v-model="chatLog" readonly placeholder="对话日志"></textarea>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pc: null,
      mediaRecorder: null,
      audioChunks: [],
      isRecording: false,
      question: '你知道5G核心网吗',
      chatLog: '',
    };
  },
  methods: {
    negotiate() {
      console.log("negotiate");
      this.pc.addTransceiver('video', { direction: 'recvonly' });
      this.pc.addTransceiver('audio', { direction: 'recvonly' });

      return this.pc.createOffer().then((offer) => {
        return this.pc.setLocalDescription(offer);
      }).then(() => {
        return new Promise((resolve) => {
          if (this.pc.iceGatheringState === 'complete') {
            resolve();
          } else {
            const checkState = () => {
              if (this.pc.iceGatheringState === 'complete') {
                this.pc.removeEventListener('icegatheringstatechange', checkState);
                resolve();
              }
            };
            this.pc.addEventListener('icegatheringstatechange', checkState);
          }
        });
      }).then(() => {
        var offer = this.pc.localDescription;
        return fetch('http://10.112.100.174:8010/offer', {
          body: JSON.stringify({
            sdp: offer.sdp,
            type: offer.type,
          }),
          headers: {
            'Content-Type': 'application/json'
          },
          method: 'POST'
        });
      }).then((response) => {
        return response.json();
      }).then((answer) => {
        document.getElementById('sessionid').value = answer.sessionid;
        return this.pc.setRemoteDescription(answer);
      }).catch((e) => {
        alert(e);
      });
    },
    start() {
      console.log("start function");
      var config = {
        sdpSemantics: 'unified-plan'
      };

      this.pc = new RTCPeerConnection(config);

      // connect audio / video
      this.pc.addEventListener('track', (evt) => {
        if (evt.track.kind == 'video') {
          document.getElementById('video').srcObject = evt.streams[0];
        } else {
          document.getElementById('audio').srcObject = evt.streams[0];
        }
      });

      document.getElementById('start').style.display = 'none';
      this.negotiate();
      document.getElementById('stop').style.display = 'inline-block';
    },
    stop() {
      console.log("stop function");
      document.getElementById('stop').style.display = 'none';
      document.getElementById('start').style.display = 'inline-block';

      // close peer connection
      setTimeout(() => {
        this.pc.close();
      }, 500);
    },
    handleRecord() {
      if (this.isRecording) {
        this.stopSound();
        this.uploadSound();
      } else {
        this.startSound();
      }
    },
    startSound() {
      this.audioChunks = [];
      navigator.mediaDevices.getUserMedia({ audio: true })
        .then(stream => {
          this.mediaRecorder = new MediaRecorder(stream);
          this.mediaRecorder.ondataavailable = event => {
            if (event.data.size > 0) {
              this.audioChunks.push(event.data);
            }
          };
          this.mediaRecorder.onstop = () => {
            const audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
            const audioUrl = URL.createObjectURL(audioBlob);
            document.getElementById('audioPlayer').src = audioUrl;
          };
          this.mediaRecorder.start();
          this.isRecording = true;
        })
        .catch(error => {
          console.error('getUserMedia error:', error);
        });
    },
    stopSound() {
      if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
        this.mediaRecorder.stop();
        this.isRecording = false;
      }
    },
    uploadSound() {
      console.log("开始回答问题");
      if (this.audioChunks.length == 0) {
        console.log("等待录音数据...");
        return;
      }
      if (document.getElementById('audioPlayer').src == '') {
        console.log("音频为空");
        return;
      }
      const audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
      const formData = new FormData();
      formData.append('audio', audioBlob, 'recorded_audio.wav');
      formData.append('sessionid', parseInt(document.getElementById('sessionid').value));

      fetch('http://10.112.100.174:8010/uploadsound', {
        method: 'POST',
        body: formData
      })
        .then(response => response.json())
        .then(data => {
          this.chatLog += data['data'] + '\n';
        })
        .catch(error => {
          console.error('Upload error:', error);
        });
    },
    sendQuestion() {
      const formData = new FormData();
      formData.append('sessionid', parseInt(document.getElementById('sessionid').value));
      formData.append('question', this.question);

      fetch('http://10.112.100.174:8010/yiyan', {
        method: 'POST',
        body: formData
      })
        .then(response => response.json())
        .then(data => {
          this.chatLog += "【提问】:" + this.question + '\n';
          this.chatLog += "【回答】:" + data.answer + '\n';
          this.question = '';
        })
        .catch(error => {
          console.error('Error:', error);
        });
    }
  }
};
</script>

<style scoped>
.human-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  height: 100%;
  box-sizing: border-box;
  font-size: 24px;
  font-weight: bold;
  align-items: flex-start;
  gap: 30px;
}

.video-wrapper {
  flex: 1;
  height: 100%;
}

.demo-video {
  width: 100%;
  height: 100%;
}

.digital-human-features {
  display: flex;
  flex-direction: column;
  width: 60%;
  gap: 10px;
  margin-top: 50px;
}

.input-container {
  display: flex;
  align-items: center;
  gap: 0;
}

.input-container textarea {
  flex: 4;
  height: 100px;
  resize: none;
  box-sizing: border-box;
}

.input-container button {
  flex: 1;
  height: 100px;
  box-sizing: border-box;
  background-color: #007BFF;
  font-weight: bold;
  cursor: pointer;
  border: none;
}

.audio-container {
  display: flex;
  align-items: center;
  gap: 0;
}

.audio-container audio {
  flex: 4;
}

.audio-container button {
  flex: 1;
  height: 100%;
  box-sizing: border-box;
  background-color: #90EE90;
  color: black;
  font-weight: bold;
  cursor: pointer;
  border: none;
}

#chatlog {
  width: 100%;
  height: 100px;
  resize: none;
  box-sizing: border-box;
  overflow-y: auto;
}

button {
  border-radius: 4px;
  padding: 10px 20px;
  color: #000;
  border: none;
  cursor: pointer;
  font-weight: bold;
  transition: background-color 0.3s ease;
}

#start {
  background-color: #90EE90;
}

#stop {
  background-color: #FFB6C1;
}

#chat_btn {
  background-color: #90EE90;
}

#upload_sound_btn {
  background-color: #90EE90;
}

button:hover {
  opacity: 0.8;
}
</style>
